#include "stdafx.h"
#include "Text.h"

#include "GlobalAppData.h"
#include "InputLayouts.h"
#include "LoadTexture.h"
#include "LoadShader.h"

#include "Renderer.h"

#define FONT_TEX_WIDTH 16
#define FONT_TEX_HEIGHT 6

#define CHAR_WIDTH 12
#define CHAR_HEIGHT 12

using namespace mgfx;

static VertexBufferID vertexBuffer;
static IndexBufferID indexBuffer;

static uint length = 128;

static TextureID fontTex;
static ShaderID textShader;

void mgfx::Text2D::init(ID3D11Device * dev, ID3D11DeviceContext * devCon)
{
	fontTex = loadTextureFromFile("font.bmp");
	textShader = loadShaderFromFile("Font.fx");

	vertexBuffer = Renderer::Instance->addVertexBuffer(NULL, length * 4, sizeof(VertexPositionTexture), true);

	short * indices = new short[length * 6];
	for (uint i = 0; i < length; i++)
	{
		indices[i * 6 + 0] = i * 4 + 0;
		indices[i * 6 + 1] = i * 4 + 1;
		indices[i * 6 + 2] = i * 4 + 2;

		indices[i * 6 + 3] = i * 4 + 2;
		indices[i * 6 + 4] = i * 4 + 3;
		indices[i * 6 + 5] = i * 4 + 0;
	}
	indexBuffer = Renderer::Instance->addIndexBuffer(indices, length * 6, sizeof(short));
	delete indices;
}

void mgfx::Text2D::deinit()
{
}

static void setText(const std::string & text)
{
	uint size = (std::min)(length, text.size());

	VertexPositionTexture * vertices = (VertexPositionTexture*)Renderer::Instance->mapVertexBuffer(vertexBuffer);

	float charSSWidth = 2 * CHAR_WIDTH / (float)mcore::GlobalAppData::Instance.ScreenWidth;
	float charSSHeight = 2 * CHAR_WIDTH / (float)mcore::GlobalAppData::Instance.ScreenHeight;

	float fontTexWidthInv = 1.0f / FONT_TEX_WIDTH;
	float fontTexHeightInv = 1.0f / FONT_TEX_HEIGHT;

	for(uint i = 0; i < size; i++)
	{
		uint column = (text[i] - 32) % FONT_TEX_WIDTH;
		uint row = (text[i] - 32) / FONT_TEX_WIDTH;
		assert(row < FONT_TEX_HEIGHT);

		//vertices[i * 4 + 0].Position = XMFLOAT3((i + 0) * charSSWidth,  0 * charSSHeight, 0.5f);
		//vertices[i * 4 + 1].Position = XMFLOAT3((i + 1) * charSSWidth,  0 * charSSHeight, 0.5f);
		//vertices[i * 4 + 2].Position = XMFLOAT3((i + 1) * charSSWidth, -1 * charSSHeight, 0.5f);
		//vertices[i * 4 + 3].Position = XMFLOAT3((i + 0) * charSSWidth, -1 * charSSHeight, 0.5f);

		vertices[i * 4 + 0].Position = XMFLOAT3(i * charSSWidth * 0.75f,  0 * charSSHeight, 0.5f);
		vertices[i * 4 + 1].Position = XMFLOAT3(i * charSSWidth * 0.75f + charSSWidth,  0 * charSSHeight, 0.5f);
		vertices[i * 4 + 2].Position = XMFLOAT3(i * charSSWidth * 0.75f + charSSWidth, -1 * charSSHeight, 0.5f);
		vertices[i * 4 + 3].Position = XMFLOAT3(i * charSSWidth * 0.75f, -1 * charSSHeight, 0.5f);

		vertices[i * 4 + 0].TextureCoord = XMFLOAT2((column + 0) * fontTexWidthInv, (row + 0) * fontTexHeightInv);
		vertices[i * 4 + 1].TextureCoord = XMFLOAT2((column + 1) * fontTexWidthInv, (row + 0) * fontTexHeightInv);
		vertices[i * 4 + 2].TextureCoord = XMFLOAT2((column + 1) * fontTexWidthInv, (row + 1) * fontTexHeightInv);
		vertices[i * 4 + 3].TextureCoord = XMFLOAT2((column + 0) * fontTexWidthInv, (row + 1) * fontTexHeightInv);
	}

	Renderer::Instance->unmapVertexBuffer(vertexBuffer);
}

void mgfx::Text2D::draw(const std::string & text, uint x, uint y, float scale)
{
	setText(text);

	uint scrWid = mcore::GlobalAppData::Instance.ScreenWidth;
	uint scrHei = mcore::GlobalAppData::Instance.ScreenHeight;

	XMMATRIX transform = XMMatrixMultiply(
		XMMatrixScaling(scale, scale, 1.0f),
		XMMatrixTranslation(x / float(scrWid / 2) - 1.0f, -int(y) / float(scrHei / 2) + 1.0f, 0.0f)
	);

	Renderer * renderer = Renderer::Instance;
	renderer->setVertexBuffer(vertexBuffer);
	renderer->setIndexBuffer(indexBuffer);
	renderer->setPrimitiveType(TRIANGLE_LIST);
	renderer->setVertexFormat(mgfx::VertexPositionTexture::VertexFormat);

	renderer->setShader(textShader);

	renderer->setShaderMatrix("gWorld", (float*)&transform);
	renderer->setShaderResource("gTexture", fontTex);

	renderer->drawIndexed(text.size() * 6);

	//HR(effect->Effect->GetVariableByName("gTexture")->AsShaderResource()->SetResource(NULL));
}

